package cn.edu.gzhu.workOrderManagement.service.impl;

import cn.edu.gzhu.workOrderManagement.enumeration.UserAuthorityEnum;
import cn.edu.gzhu.workOrderManagement.mapper.TeamMapper;
import cn.edu.gzhu.workOrderManagement.mapper.UserMapper;
import cn.edu.gzhu.workOrderManagement.mapper.OrganizationMapper;
import cn.edu.gzhu.workOrderManagement.pojo.dto.user.*;
import cn.edu.gzhu.workOrderManagement.pojo.entity.Organization;
import cn.edu.gzhu.workOrderManagement.pojo.entity.Team;
import cn.edu.gzhu.workOrderManagement.pojo.entity.User;
import cn.edu.gzhu.workOrderManagement.pojo.vo.UserLoginVo;
import cn.edu.gzhu.workOrderManagement.pojo.vo.UserVo;
import cn.edu.gzhu.workOrderManagement.properties.JwtProperties;
import cn.edu.gzhu.workOrderManagement.service.OrganizationService;
import cn.edu.gzhu.workOrderManagement.service.UserService;
import cn.edu.gzhu.workOrderManagement.util.JwtUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 普通用户接口实现类
 * 鉴权与授权写在拦截器中，仅有普通的增删查改
 * @author chen xi
 */
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService {
    @Autowired
    OrganizationService organizationService;
    @Autowired
    OrganizationMapper organizationMapper;
    @Autowired
    TeamMapper teamMapper;
    @Autowired
    JwtProperties jwtProperties;
    @Autowired
    private UserMapper userMapper;

    /**
     * 注册，插入成功返回1失败返回0,使用sha256加密密码
     * @param userRegisterDto 包含username password organization authority
     * @return 返回0则注册失败
     */
    @Override
    public Boolean saveUser(UserRegisterDto userRegisterDto) {
        //首先查看组织是否存在，不存在直接返回false

        Organization organization = organizationMapper.selectOne(new QueryWrapper<Organization>().eq("name", userRegisterDto.getOrganization()));

        //查看公司是否存在或启用
        if (organization==null|| !organization.getIsAvailable()) {
            return false;
        }
        //查看组别是否存在
        Team team = teamMapper.selectById(userRegisterDto.getTeamId());
        if (team==null){
            return false;
        }
        //查看组别是否属于该公司
        if (!team.getOriginOrganization().equals(organization.getName())){
            return false;
        }
        //校验公司和组织人数是否超过上限
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>()
                .eq(User::getOrganization,userRegisterDto.getOrganization());
        Integer sum = baseMapper.selectCount(lqw);
        if (sum>=organization.getCapacity()) {
            return false;
        }
        lqw.eq(User::getTeamId,userRegisterDto.getTeamId());
        Integer count = baseMapper.selectCount(lqw);
        if (count>=team.getCapacity()) {
            return false;
        }

        //sha256摘要，转换密码，准备插入
        String password = userRegisterDto.getPassword();
        String passwordBySha256 = DigestUtil.sha256Hex(password);

        User user = new User();

        BeanUtils.copyProperties(userRegisterDto,user);

        user.setPassword(passwordBySha256);
        user.setIsAvailable(false);
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());

        return this.save(user);
    }

    /**
     * 登入颁发jwt令牌，登入成功返回userVo中的用户数据以及JWT令牌，不成功返回空对象
     * @param userLoginDto 包含username password
     * @return
     */
    @Override
    public UserLoginVo getUserByUsernameAndPW(UserLoginDto userLoginDto) {
        // 1️⃣ 把密码转换为 SHA-256 摘要
        String passwordBySha256 = DigestUtil.sha256Hex(userLoginDto.getPassword());

        // 2️⃣ 构造查询条件
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, userLoginDto.getUsername())
                .eq(User::getPassword, passwordBySha256)
                .eq(User::getIsAvailable, true); // 只有启用的用户才能登录

        // 3️⃣ 查询用户
        User user = userMapper.selectOne(queryWrapper);
        if (user == null) {

            return null;
        }
        //查看组织是否启用，未启用不能登入
        if(!user.getAuthority().equals(UserAuthorityEnum.ADMIN)) { //TODO 此处是为了管理员不在任何一个组织框架内也能登入
            Organization organization = organizationMapper.selectOne(new LambdaQueryWrapper<Organization>().eq(Organization::getName, user.getOrganization()));
            if (organization==null||!organization.getIsAvailable()) {

                return null;

            }
        }
        // 4️⃣ 构造返回对象 UserLoginVo
        UserLoginVo userLoginVo = new UserLoginVo();
        BeanUtils.copyProperties(user, userLoginVo);

        // 5️⃣ 生成 JWT 令牌
        HashMap<String, Object> claims = new HashMap<>();
        claims.put("username", user.getUsername());
        claims.put("authority", user.getAuthority().getRole());
        claims.put("organization", user.getOrganization());

        String jwt = JwtUtil.createJWT(jwtProperties.getUserSecretKey(), jwtProperties.getUserTtl(), claims);
        userLoginVo.setToken(jwt);

        return userLoginVo;
    }


    /**
     * 按条件查询组织中的用户
     * @param userListDto
     * @return
     */
    @Override
    public IPage<UserVo> listByConditions(UserListDto userListDto) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();

        // 条件构造
        if (StringUtils.isNotBlank(userListDto.getName())){
            queryWrapper.like(User::getName, userListDto.getName());
        }
        if (StringUtils.isNotBlank(userListDto.getUsername())) {
            queryWrapper.eq(User::getUsername, userListDto.getUsername());
        }
        if (userListDto.getIsAvailable() != null) {
            queryWrapper.eq(User::getIsAvailable, userListDto.getIsAvailable());
        }
        if (userListDto.getAuthority() != null) {
            queryWrapper.eq(User::getAuthority, userListDto.getAuthority());
        }
        if (userListDto.getTeamId()!=null){
            queryWrapper.eq(User::getTeamId,userListDto.getTeamId());
        }
        if (StringUtils.isNotBlank(userListDto.getOrganization())) {
            queryWrapper.like(User::getOrganization, userListDto.getOrganization());
        }

        if (StringUtils.isNotBlank(userListDto.getTeamName())) {
            List<Team> teams = teamMapper.selectList(new LambdaQueryWrapper<Team>().like(Team::getTeamName, userListDto.getTeamName()));
            List<Integer> teamIds = teams.stream().map(Team::getId).toList();
            queryWrapper.in(User::getTeamId, teamIds);

        }
        // 分页查询
        Page<User> page = new Page<>(userListDto.getStartPage(), userListDto.getPageSize());
        IPage<User> userPage = this.page(page, queryWrapper);

        // 转换为 VO
        List<UserVo> voList = userPage.getRecords().stream()
                .map(user -> {
                    UserVo userVo = new UserVo();
                    BeanUtils.copyProperties(user, userVo);
                    Team team = teamMapper.selectById(user.getTeamId());
                    if (team != null) {
                        userVo.setTeamName(team.getTeamName());
                    }
                    return userVo;
                }).collect(Collectors.toList());

        IPage<UserVo> voPage = new Page<>(userPage.getCurrent(), userPage.getSize(), userPage.getTotal());
        voPage.setRecords(voList);
        return voPage;
    }
    /**
     * 修改用户属性
     * @param userUpdateDto
     * @return
     */
    @Override
    public Boolean updateUser(UserAuthorityEnum userAuthorityEnum, UserUpdateDto userUpdateDto) {
        //User user = new User();
        //BeanUtils.copyProperties(userUpdateDto,user);
        //如果需要更新密码，则把密码先用sha256摘要再更新

        LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(User::getUsername, userUpdateDto.getUsername());
        User targetUser = this.getOne(updateWrapper);
        if (!userAuthorityEnum.equals(UserAuthorityEnum.ADMIN)&&userUpdateDto.getPassword()!=null) {
            String oldPassword = userUpdateDto.getOldPassword();
            if (oldPassword==null){
                return false;
            }
            String oldPD = DigestUtil.sha256Hex(oldPassword);
            if (!targetUser.getPassword().equals(oldPD)) {
                return false;
            }
        }
        if(StringUtils.isNotBlank( userUpdateDto.getPassword())){
           updateWrapper.set(User::getPassword,DigestUtil.sha256Hex(userUpdateDto.getPassword()));
        }
        if (StringUtils.isNotBlank(userUpdateDto.getName())){
            updateWrapper.set(User::getName, userUpdateDto.getName());
        }
        if (userUpdateDto.getAuthority()!=null) {
            updateWrapper.set(User::getAuthority, userUpdateDto.getAuthority());
        }
        if (StringUtils.isNotBlank(userUpdateDto.getOrganization())) {
            updateWrapper.set(User::getOrganization, userUpdateDto.getOrganization());
        }
        if (userUpdateDto.getIsAvailable() != null) {
            updateWrapper.set(User::getIsAvailable, userUpdateDto.getIsAvailable());
        }
        if (userUpdateDto.getTeamId()!=null) {
            updateWrapper.set(User::getTeamId, userUpdateDto.getTeamId());
        }
        updateWrapper.set(User::getUpdateTime, LocalDateTime.now());
        return this.update(updateWrapper);

    }

    /**
     * 按用户名批量删除用户
     * @param userDeleteDto
     * @return
     */
    @Override
    public Boolean deleteUsersByUsernames(UserDeleteDto userDeleteDto) {
        List<String> usernames = userDeleteDto.getUsernames();

        return this.remove(new LambdaQueryWrapper<User>().in(User::getUsername, usernames));
    }

    /**
     * 根据组织名删除组织下所有用户
     *
     * @param organization
     * @return
     */
    @Override
    public Boolean deleteUsersByOrganization(String organization) {
        if (StringUtils.isBlank(organization)) {
            return false; // 组织名称为空，直接返回
        }

        // 执行删除
        return this.remove(new LambdaQueryWrapper<User>()
                .eq(User::getOrganization, organization));
    }

    /**
     * @param userDeleteDto
     * @return
     */
    @Override
    public Boolean activateUsers(UserDeleteDto userDeleteDto) {
        List<String> usernames = userDeleteDto.getUsernames();
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<User>().in("username", usernames);
        User available = User.builder().isAvailable(true).updateTime(LocalDateTime.now()).build();
        return this.update(available, userQueryWrapper);
    }


}
